home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / EasyTools / full packs / DSound150 / Play.c < prev    next >
C/C++ Source or Header  |  1994-07-18  |  19KB  |  713 lines

  1.  
  2. /*************************************************************************/
  3. /*                   Play.c                 */
  4. /*Contains code used to play samples (mono out of one or both speakers,  */
  5. /*and stereo).                                 */
  6. /*************************************************************************/
  7.  
  8. #include <exec/types.h>
  9. #include <exec/exec.h>
  10. #include <devices/audio.h>
  11. #include <dos/dos.h>
  12. #include <intuition/intuition.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <graphics/gfxbase.h>
  15. #include <stdlib.h>
  16.  
  17. #include "dsound.h"
  18.  
  19. #include <proto/intuition.h>
  20. #include <proto/exec.h>
  21. #include <proto/dos.h>
  22.  
  23. UBYTE rightAMap[]={4,2,1,8};
  24. UBYTE leftAMap[]={1,8,2,4};
  25. UBYTE eitherAMap[]={1,2,4,8};
  26. UBYTE bothAMap[]={8,3,5,10};
  27.  
  28. extern UBYTE volume;
  29. extern UWORD speed;
  30. extern ULONG bufSize;
  31.  
  32. extern BOOL readAll;
  33. extern BOOL loop;
  34. extern struct Window *window;
  35.  
  36. /*Play a sample out of one speaker (left, right, or either)*/
  37. void playMonoSample(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
  38.             ULONG len)
  39. {
  40.    struct IOAudio *iob1,*iob2;
  41.    ULONG toRead;
  42.    ULONG sampleSize=len;
  43.    BOOL done=FALSE;
  44.    UBYTE *allocationMap;
  45.  
  46.    /*Load the entire sample into memory, if the user so specified*/
  47.    if(readAll)
  48.    {
  49.       storeLeft(file,len,bufSize);
  50.       file=0L;
  51.    }
  52.  
  53.    /*Decide which audio channel will be allocated*/
  54.    switch(audioChannel)
  55.    {
  56.       case MONO_LEFT:
  57.      allocationMap=leftAMap;
  58.      break;
  59.       case MONO_RIGHT:
  60.      allocationMap=rightAMap;
  61.      break;
  62.       case UNSPECIFIED:
  63.      allocationMap=eitherAMap;
  64.      break;
  65.    }
  66.  
  67.    /*Get the first audio channel*/
  68.    iob1=GetAudioChannel(bufSize,allocationMap);
  69.    if(iob1==NULL)
  70.    {
  71.       WriteMsg("Couldn't create the first buffer\n");
  72.       cleanup(150);
  73.    }
  74.  
  75.    /* If the user didn't specify a volume, get it from the VHDR */
  76.    if(volume==0)
  77.       volume=(vhdr->volume>>10);
  78.  
  79.    /* If the VHDR gave a volume of zero, use maximum volume*/
  80.    if(volume==0)
  81.       volume=64;
  82.  
  83.    /* Get the samples/sec rate (either the rate given by the user, or the*/
  84.    /* rate found in the VHDR) */
  85.    if(speed==0)
  86.       speed=1000000000/(vhdr->samplesPerSec*279);
  87.    else
  88.       speed=1000000000/(speed*279);
  89.  
  90.    InitAudioChannel(iob1,volume,speed);
  91.  
  92.    /*Get the 2nd audio channel*/
  93.    iob2=DuplicateAudioChannel(iob1);
  94.  
  95.    if(iob2==NULL)
  96.    {
  97.       FreeAudioChannel(iob1);
  98.       WriteMsg("Couldn't create the second buffer\n");
  99.       cleanup(175);
  100.    }
  101.  
  102.    /* Load the first buffer*/
  103.    toRead=MIN(len,bufSize);
  104.    LoadAudioBuffer(file,iob1,toRead);
  105.  
  106.    len-=toRead;
  107.    if(len==0 && loop)
  108.    {
  109.       len=sampleSize;
  110.       Seek(file,-sampleSize,OFFSET_CURRENT);
  111.    }
  112.  
  113.    /*Store the number of samples to be played*/
  114.    iob1->ioa_Length=toRead;
  115.  
  116.    /* Make sure there's enough data so that we have something to put in */
  117.    /* the second buffer */
  118.    if(len!=0)
  119.    {
  120.       toRead=MIN(len,bufSize);
  121.       LoadAudioBuffer(file,iob2,toRead);
  122.       len-=toRead;
  123.       if(len==0 && loop)
  124.       {
  125.      len=sampleSize;
  126.      Seek(file,-sampleSize,OFFSET_CURRENT);
  127.       }
  128.       iob2->ioa_Length=toRead;
  129.    }
  130.    else
  131.       /* It appears that the entire sound sample is small enough to */
  132.       /* fit into the first buffer, so don't play the second */
  133.       iob2->ioa_Length=0;
  134.  
  135.    /*And queue up the play requests*/
  136.    BeginIO((struct IORequest *)iob1);
  137.    if(iob2->ioa_Length!=0)
  138.       BeginIO((struct IORequest *)iob2);
  139.  
  140.    /* If the sound sample was small enough to fit into the two buffers, */
  141.    /* play them then finish up */
  142.    if(len==0)
  143.    {
  144.       Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) +
  145.        (1<<window->UserPort->mp_SigBit));
  146.  
  147.                            /*    vvvv Bug fix */
  148.       if(iob2->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
  149.      Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  150.           (1<<window->UserPort->mp_SigBit));
  151.  
  152.      done=TRUE;
  153.    }
  154.  
  155.    /*Otherwise, play those samples then read more from disk*/
  156.  
  157.    /*Loop while there's stuff to read*/
  158.    while(!done)
  159.    {
  160.       /*Fill the first buffer*/
  161.       Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  162.        (1<<window->UserPort->mp_SigBit));
  163.  
  164.       toRead=MIN(len,bufSize);
  165.  
  166.       if(GetMsg(window->UserPort)!=NULL)
  167.       {
  168.      done=TRUE;
  169.      break;
  170.       }
  171.       else
  172.      if(toRead==0)
  173.      {
  174.         /*If there's no stuff left to read, wait 'till the second buffer*/
  175.         /*finishes, then quit*/
  176.         Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  177.          (1<<window->UserPort->mp_SigBit));
  178.         done=TRUE;
  179.         break;
  180.      }
  181.  
  182.       LoadAudioBuffer(file,iob1,toRead);
  183.       len-=toRead;
  184.       if(len==0 && loop)
  185.       {
  186.      len=sampleSize;
  187.      Seek(file,-sampleSize,OFFSET_CURRENT);
  188.       }
  189.  
  190.       iob1->ioa_Length=toRead;
  191.  
  192.       /*Play the first buffer*/
  193.       BeginIO((struct IORequest *)iob1);
  194.  
  195.       /*Wait for the second buffer to finish*/
  196.       Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  197.        (1<<window->UserPort->mp_SigBit));
  198.  
  199.       toRead=MIN(len,bufSize);
  200.  
  201.       if(GetMsg(window->UserPort)!=NULL)
  202.       {
  203.      done=TRUE;
  204.      break;
  205.       }
  206.       else
  207.      if(toRead==0)
  208.      {
  209.         /*If there's no stuff left to read, wait 'till the first buffer*/
  210.         /*finishes, then quit*/
  211.         Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  212.          (1<<window->UserPort->mp_SigBit));
  213.         done=TRUE;
  214.         break;
  215.      }
  216.  
  217.       /*Reload it*/
  218.       LoadAudioBuffer(file,iob2,toRead);
  219.       len-=toRead;
  220.       if(len==0 && loop)
  221.       {
  222.      len=sampleSize;
  223.      Seek(file,-sampleSize,OFFSET_CURRENT);
  224.       }
  225.       iob2->ioa_Length=toRead;
  226.  
  227.       /*Play it*/
  228.       BeginIO((struct IORequest *)iob2);
  229.    }
  230.  
  231.    /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
  232.    /*how much memory to free*/
  233.    iob1->ioa_Length=iob2->ioa_Length=bufSize;
  234.  
  235.    FreeAudioChannel(iob1);
  236.    DeleteDuplication(iob2);
  237.  
  238.    return;
  239. }
  240.  
  241. /*Play a stereo sample out of both speakers*/
  242. /*If the user specifies that just one of the two stereo channels will*/
  243. /*be played, DSound.c calls playMonoSample*/
  244.  
  245. void playStereoSample(BPTR leftFile,channel audioChannel,
  246.               struct Voice8Header *vhdr, ULONG length, char *filename)
  247. {
  248.    struct IOAudio *iob1_right,*iob2_right,*iob1_left,*iob2_left;
  249.    ULONG toRead;
  250.    ULONG sampleSize=length;
  251.    BOOL done=FALSE;
  252.    BPTR rightFile;
  253.  
  254.    /*Open the file again*/
  255.    rightFile=dupFileHandle(leftFile,filename);
  256.  
  257.    /*And position ourselves at the start of the right channel's data*/
  258.    Seek(rightFile,length,OFFSET_CURRENT);
  259.  
  260.    /*Read the entire sample into memory, if specified*/
  261.    if(readAll)
  262.    {
  263.       storeLeft(leftFile,length,bufSize);
  264.       storeRight(rightFile,length,bufSize);
  265.       Close(rightFile);
  266.       leftFile=0L;
  267.       rightFile=4L;
  268.    }
  269.  
  270.    /*Get the first audio channel*/
  271.    iob1_left=GetAudioChannel(bufSize,leftAMap);
  272.    if(iob1_left==NULL)
  273.    {
  274.       WriteMsg("Couldn't create the first stereo buffer\n");
  275.       cleanup(150);
  276.    }
  277.  
  278.    iob1_right=GetAudioChannel(bufSize,rightAMap);
  279.    if(iob1_right==NULL)
  280.    {
  281.       WriteMsg("Couldn't create the second stereo buffer\n");
  282.       cleanup(150);
  283.    }
  284.  
  285.    /* If the user didn't specify a volume, get it from the VHDR */
  286.    if(volume==0)
  287.       volume=(vhdr->volume>>10);
  288.  
  289.    /* If the VHDR gave a volume of zero, use maximum volume*/
  290.    if(volume==0)
  291.       volume=64;
  292.  
  293.    /* Get the samples/sec rate (either the rate given by the user, or the*/
  294.    /* rate found in the VHDR) */
  295.    if(speed==0)
  296.       speed=1000000000/(vhdr->samplesPerSec*279);
  297.    else
  298.       speed=1000000000/(speed*279);
  299.  
  300.    InitAudioChannel(iob1_left,volume,speed);
  301.    InitAudioChannel(iob1_right,volume,speed);
  302.  
  303.    /*Get the 2nd audio channel*/
  304.    iob2_left=DuplicateAudioChannel(iob1_left);
  305.  
  306.    if(iob2_left==NULL)
  307.    {
  308.       FreeAudioChannel(iob1_left);
  309.       FreeAudioChannel(iob1_right);
  310.       WriteMsg("Couldn't create the second buffer");
  311.       cleanup(175);
  312.    }
  313.  
  314.    iob2_right=DuplicateAudioChannel(iob1_right);
  315.    if(iob2_right==NULL)
  316.    {
  317.       FreeAudioChannel(iob1_left);
  318.       DeleteDuplication(iob2_left);
  319.       FreeAudioChannel(iob1_right);
  320.       WriteMsg("Couldn't create the second buffer");
  321.       cleanup(175);
  322.    }
  323.  
  324.  
  325.    /* Load the first buffer*/
  326.    toRead=MIN(length,bufSize);
  327.    LoadAudioBuffer(leftFile,iob1_left,toRead);
  328.    LoadAudioBuffer(rightFile,iob1_right,toRead);
  329.    iob1_left->ioa_Length=iob1_right->ioa_Length=toRead;
  330.    iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
  331.  
  332.    length-=toRead;
  333.    if(length==0 && loop)
  334.    {
  335.       length=sampleSize;
  336.       Seek(leftFile,-sampleSize,OFFSET_CURRENT);
  337.       Seek(rightFile,-sampleSize,OFFSET_CURRENT);
  338.    }
  339.  
  340.    /* Make sure there's enough data so that we have something to put in */
  341.    /* the second buffer */
  342.    if(length!=0)
  343.    {
  344.       toRead=MIN(length,bufSize);
  345.       LoadAudioBuffer(leftFile,iob2_left,toRead);
  346.       LoadAudioBuffer(rightFile,iob2_right,toRead);
  347.       length-=toRead;
  348.       if(length==0 && loop)
  349.       {
  350.      length=sampleSize;
  351.      Seek(leftFile,-sampleSize,OFFSET_CURRENT);
  352.      Seek(rightFile,-sampleSize,OFFSET_CURRENT);
  353.       }
  354.  
  355.       iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
  356.    }
  357.    else
  358.       /* It appears that the entire sound sample is small enough to */
  359.       /* fit into the first buffer, so don't play the second */
  360.       iob2_left->ioa_Length=iob2_right->ioa_Length=0;
  361.  
  362.    /*And queue up the play requests*/
  363.    BeginIO((struct IORequest *)iob1_left);
  364.    BeginIO((struct IORequest *)iob1_right);
  365.    if(iob2_left->ioa_Length!=0)
  366.    {
  367.       BeginIO((struct IORequest *)iob2_left);
  368.       BeginIO((struct IORequest *)iob2_right);
  369.    }
  370.  
  371.    /* If the sound sample was small enough to fit into the two buffers, */
  372.    /* play them then finish up */
  373.    if(length==0)
  374.    {
  375.       Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  376.        (1<<window->UserPort->mp_SigBit));
  377.  
  378.       if(iob2_left->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
  379.      Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  380.           (1<<window->UserPort->mp_SigBit));
  381.  
  382.       done=TRUE;
  383.    }
  384.    /*Otherwise, play those samples then read more from disk*/
  385.  
  386.    /*Loop while there's stuff to read*/
  387.    while(!done)
  388.    {
  389.       /*Wait for the first buffer to finish playing*/
  390.       Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  391.        (1<<window->UserPort->mp_SigBit));
  392.  
  393.       toRead=MIN(length,bufSize);
  394.  
  395.       if(GetMsg(window->UserPort)!=NULL)
  396.       {
  397.      done=TRUE;
  398.      break;
  399.       }
  400.       else
  401.      if(toRead==0)
  402.      {
  403.         /*If there's no stuff left to read, wait 'till the second buffer*/
  404.         /*finishes, then quit*/
  405.         Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  406.          (1<<window->UserPort->mp_SigBit));
  407.         done=TRUE;
  408.         break;
  409.      }
  410.  
  411.       LoadAudioBuffer(leftFile,iob1_left,toRead);
  412.       LoadAudioBuffer(rightFile,iob1_right,toRead);
  413.       length-=toRead;
  414.       if(length==0 && loop)
  415.       {
  416.      length=sampleSize;
  417.      Seek(leftFile,-sampleSize,OFFSET_CURRENT);
  418.      Seek(rightFile,-sampleSize,OFFSET_CURRENT);
  419.       }
  420.  
  421.       iob1_left->ioa_Length=iob1_right->ioa_Length=toRead;
  422.  
  423.       /*Play the first buffer*/
  424.       BeginIO((struct IORequest *)iob1_left);
  425.       BeginIO((struct IORequest *)iob1_right);
  426.  
  427.       /*Wait for the second buffer to finish*/
  428.       Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  429.        (1<<window->UserPort->mp_SigBit));
  430.  
  431.       toRead=MIN(length,bufSize);
  432.  
  433.       if(GetMsg(window->UserPort)!=NULL)
  434.       {
  435.      done=TRUE;
  436.      break;
  437.       }
  438.       else
  439.      if(toRead==0)
  440.      {
  441.         /*If there's no stuff left to read, wait 'till the first buffer*/
  442.         /*finishes, then quit*/
  443.         Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  444.          (1<<window->UserPort->mp_SigBit));
  445.         done=TRUE;
  446.         break;
  447.      }
  448.  
  449.       /*Reload it*/
  450.       LoadAudioBuffer(leftFile,iob2_left,toRead);
  451.       LoadAudioBuffer(rightFile,iob2_right,toRead);
  452.       length-=toRead;
  453.       if(length==0 && loop)
  454.       {
  455.      length=sampleSize;
  456.      Seek(leftFile,-sampleSize,OFFSET_CURRENT);
  457.      Seek(rightFile,-sampleSize,OFFSET_CURRENT);
  458.       }
  459.  
  460.       iob2_left->ioa_Length=iob2_right->ioa_Length=toRead;
  461.  
  462.       /*Play it*/
  463.       BeginIO((struct IORequest *)iob2_left);
  464.       BeginIO((struct IORequest *)iob2_right);
  465.    }
  466.  
  467.    /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
  468.    /*how much memory to free*/
  469.    iob1_left->ioa_Length=iob2_left->ioa_Length=bufSize;
  470.    iob1_right->ioa_Length=iob2_right->ioa_Length=bufSize;
  471.  
  472.    FreeAudioChannel(iob1_left);
  473.    DeleteDuplication(iob2_left);
  474.    FreeAudioChannel(iob1_right);
  475.    DeleteDuplication(iob2_right);
  476.  
  477.    if(rightFile != 4L)
  478.       Close(rightFile);
  479.  
  480.    return;
  481. }
  482.  
  483. /*Play a mono sample (or a single channel of a stereo sample) out of */
  484. /*both speakers simultaneously*/
  485. void playMonoTwice(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
  486.            ULONG length)
  487. {
  488.    struct IOAudio *iob1_right,*iob2_right,*iob1_left,*iob2_left;
  489.    ULONG toRead;
  490.    ULONG sampleSize=length;
  491.    BOOL done=FALSE;
  492.  
  493.    /*Read the entire sample into memory, if the user so specified*/
  494.    if(readAll)
  495.    {
  496.       storeLeft(file,length,bufSize);
  497.       file=0L;
  498.    }
  499.  
  500.    /*Get the first audio channel*/
  501.    iob1_left=GetAudioChannel(bufSize,leftAMap);
  502.    if(iob1_left==NULL)
  503.    {
  504.       WriteMsg("Couldn't create the first stereo buffer\n");
  505.       cleanup(150);
  506.    }
  507.  
  508.    iob1_right=GetAudioChannel(bufSize,rightAMap);
  509.    if(iob1_right==NULL)
  510.    {
  511.       WriteMsg("Couldn't create the second stereo buffer\n");
  512.       cleanup(150);
  513.    }
  514.    FreeMem(iob1_right->ioa_Data,iob1_right->ioa_Length);
  515.    iob1_right->ioa_Data=iob1_left->ioa_Data;
  516.  
  517.    /* If the user didn't specify a volume, get it from the VHDR */
  518.    if(volume==0)
  519.       volume=(vhdr->volume>>10);
  520.  
  521.    /* If the VHDR gave a volume of zero, use maximum volume*/
  522.    if(volume==0)
  523.       volume=64;
  524.  
  525.    /* Get the samples/sec rate (either the rate given by the user, or the*/
  526.    /* rate found in the VHDR) */
  527.    if(speed==0)
  528.       speed=1000000000/(vhdr->samplesPerSec*279);
  529.    else
  530.       speed=1000000000/(speed*279);
  531.  
  532.    InitAudioChannel(iob1_left,volume,speed);
  533.    InitAudioChannel(iob1_right,volume,speed);
  534.  
  535.    /*Get the 2nd audio channel*/
  536.    iob2_left=DuplicateAudioChannel(iob1_left);
  537.  
  538.    if(iob2_left==NULL)
  539.    {
  540.       FreeAudioChannel(iob1_left);
  541.       FreeAudioChannel(iob1_right);
  542.       WriteMsg("Couldn't create the second buffer");
  543.       cleanup(175);
  544.    }
  545.  
  546.    iob2_right=DuplicateAudioChannel(iob1_right);
  547.    if(iob2_right==NULL)
  548.    {
  549.       FreeAudioChannel(iob1_left);
  550.       DeleteDuplication(iob2_left);
  551.       FreeAudioChannel(iob1_right);
  552.       WriteMsg("Couldn't create the second buffer");
  553.       cleanup(175);
  554.    }
  555.    FreeMem(iob2_right->ioa_Data,iob2_right->ioa_Length);
  556.    iob2_right->ioa_Data=iob2_left->ioa_Data;
  557.  
  558.    /* Load the first buffer*/
  559.    toRead=MIN(length,bufSize);
  560.    LoadAudioBuffer(file,iob1_left,toRead);
  561.  
  562.    length-=toRead;
  563.    if(length==0 && loop)
  564.    {
  565.       length=sampleSize;
  566.       Seek(file,-sampleSize,OFFSET_CURRENT);
  567.    }
  568.  
  569.    iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
  570.  
  571.    /* Make sure there's enough data so that we have something to put in */
  572.    /* the second buffer */
  573.    if(length!=0)
  574.    {
  575.       toRead=MIN(length,bufSize);
  576.       LoadAudioBuffer(file,iob2_left,toRead);
  577.       length-=toRead;
  578.       if(length==0 && loop)
  579.       {
  580.      length=sampleSize;
  581.      Seek(file,-sampleSize,OFFSET_CURRENT);
  582.       }
  583.  
  584.       iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
  585.    }
  586.    else
  587.       /* It appears that the entire sound sample is small enough to */
  588.       /* fit into the first buffer, so don't play the second */
  589.       iob2_left->ioa_Length=iob2_right->ioa_Length=0;
  590.  
  591.    /*And queue up the play requests*/
  592.    BeginIO((struct IORequest *)iob1_left);
  593.    BeginIO((struct IORequest *)iob1_right);
  594.    if(iob2_left->ioa_Length!=0)
  595.    {
  596.       BeginIO((struct IORequest *)iob2_left);
  597.       BeginIO((struct IORequest *)iob2_right);
  598.    }
  599.  
  600.    /* If the sound sample was small enough to fit into the two buffers, */
  601.    /* play them then finish up */
  602.    if(GetMsg(window->UserPort)!=NULL)
  603.       done=TRUE;
  604.    else
  605.       if(length==0)
  606.       {
  607.      /* Bug!!! */
  608.      Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  609.           (1<<window->UserPort->mp_SigBit));
  610.  
  611.      if(iob2_left->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
  612.         Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  613.          (1<<window->UserPort->mp_SigBit));
  614.  
  615.      done=TRUE;
  616.       }
  617.    /*Otherwise, play those samples then read more from disk*/
  618.  
  619.    /*Loop while there's stuff to read*/
  620.    while(!done)
  621.    {
  622.       /*Fill the first buffer*/
  623.       Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  624.        (1<<window->UserPort->mp_SigBit));
  625.  
  626.       toRead=MIN(length,bufSize);
  627.  
  628.       if(GetMsg(window->UserPort)!=NULL)
  629.       {
  630.      done=TRUE;
  631.      break;
  632.       }
  633.       else
  634.      if(toRead==0)
  635.      {
  636.         /*If there's no stuff left to read, wait 'till the second buffer*/
  637.         /*finishes, then quit*/
  638.         Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  639.          (1<<window->UserPort->mp_SigBit));
  640.         done=TRUE;
  641.         break;
  642.      }
  643.  
  644.       LoadAudioBuffer(file,iob1_left,toRead);
  645.       length-=toRead;
  646.       if(length==0 && loop)
  647.       {
  648.      length=sampleSize;
  649.      Seek(file,-sampleSize,OFFSET_CURRENT);
  650.       }
  651.  
  652.       iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
  653.  
  654.       /*Play the first buffer*/
  655.       BeginIO((struct IORequest *)iob1_left);
  656.       BeginIO((struct IORequest *)iob1_right);
  657.  
  658.       /*Wait for the second buffer to finish*/
  659.       Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  660.        (1<<window->UserPort->mp_SigBit));
  661.  
  662.       toRead=MIN(length,bufSize);
  663.  
  664.       if(GetMsg(window->UserPort)!=NULL)
  665.       {
  666.      done=TRUE;
  667.      break;
  668.       }
  669.       else
  670.      if(toRead==0)
  671.      {
  672.         /*If there's no stuff left to read, wait 'till the first buffer*/
  673.         /*finishes, then quit*/
  674.         Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  675.          (1<<window->UserPort->mp_SigBit));
  676.         done=TRUE;
  677.         break;
  678.      }
  679.  
  680.       /*Reload it*/
  681.       LoadAudioBuffer(file,iob2_left,toRead);
  682.       length-=toRead;
  683.       if(length==0 && loop)
  684.       {
  685.      length=sampleSize;
  686.      Seek(file,-sampleSize,OFFSET_CURRENT);
  687.       }
  688.  
  689.       iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
  690.  
  691.       /*Play it*/
  692.       BeginIO((struct IORequest *)iob2_left);
  693.       BeginIO((struct IORequest *)iob2_right);
  694.    }
  695.  
  696.    /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
  697.    /*how much memory to free*/
  698.    iob1_left->ioa_Length=iob2_left->ioa_Length=bufSize;
  699.    iob1_right->ioa_Length=iob2_right->ioa_Length=bufSize;
  700.  
  701.    iob1_right->ioa_Data=NULL;
  702.    iob2_right->ioa_Data=NULL;
  703.  
  704.    FreeAudioChannel(iob1_left);
  705.    DeleteDuplication(iob2_left);
  706.    FreeAudioChannel(iob1_right);
  707.    DeleteDuplication(iob2_right);
  708.  
  709.    return;
  710. }
  711.  
  712. /*End of Play.c*/
  713.